package com.icloud.wallet.boot.schedule;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.icloud.common.core.api.CommonResult;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.web.constants.UrlConstants;
import com.icloud.common.web.exception.ApiException;
import com.icloud.wallet.boot.constant.WalletConstants;
import com.icloud.common.database.enums.JournalStateEnum;
import com.icloud.wallet.boot.mapper.TCollectionJournalMapper;
import com.icloud.wallet.boot.model.TCollectionJournal;
import com.icloud.wallet.boot.vo.CollectVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class CollectTask {
    @Autowired
    private TCollectionJournalMapper tCollectionJournalMapper;
    @Autowired
    private RestTemplate restTemplate;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void collect(){
        LambdaQueryWrapper<TCollectionJournal> collectQuery = new LambdaQueryWrapper<>();
        collectQuery.eq(TCollectionJournal::getJournalState, JournalStateEnum.PENDING.getCode());
        //collectQuery.isNull(TCollectionJournal::getTxHash);
        List<TCollectionJournal> collectList = tCollectionJournalMapper.selectList(collectQuery);
        if(CollectionUtils.isEmpty(collectList)){
            return;
        }
        List<TCollectionJournal> unCollect = collectList.stream().filter(c->StringUtils.isBlank(c.getTxHash())).collect(Collectors.toList());

        for(TCollectionJournal un : unCollect){
            CollectVO collectVO = new CollectVO();
            collectVO.setCryptoCurrency(un.getCryptoCurrency());
            collectVO.setContractAddr(un.getContractAddr());
            collectVO.setFromAddress(un.getPayAddr());
            collectVO.setGasPr(WalletConstants.GAS_PR);
            collectVO.setToAddress(WalletConstants.COLLECT_ADDRESS);
            // 单位为BNB,不是WEI
            collectVO.setAmount(un.getAmount());
            String txHash = null;
            try {
                txHash = callCollect(un.getCustomerId(), collectVO);
            }catch(Exception e){
                log.warn("Call collect error");
                continue;
            }

            TCollectionJournal updateCollection = TCollectionJournal.builder()
                    .id(un.getId())
                    .txHash(txHash)
                    .journalState(JournalStateEnum.FINISHED.getCode())
                    .remark("归集已处理")
                    .build();
            tCollectionJournalMapper.updateById(updateCollection);
        }
    }

    private String callCollect(Long customerId, CollectVO collectVO){
        String txHash = null;
        ResponseEntity<CommonResult> collectResp = restTemplate.postForEntity(UrlConstants.API_COLLECT_URL, collectVO, CommonResult.class);
        if (collectResp.getStatusCode() == HttpStatus.OK) {
            CommonResult result = collectResp.getBody();
            if(result!=null){
                Map data = (Map)result.getData();
                txHash = (String)data.get("hash");
            }
        }
        if(StringUtils.isBlank(txHash)){
            log.warn("客户[{}]归集失败. {}", customerId, collectResp.getStatusCodeValue());
            throw new ApiException(ResultCode.TX_FAILED);
        }
        return txHash;
    }
}
